home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 176-200 / disk_199 / asimplex / mpsx.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  47KB  |  1,514 lines

  1. /*****************************************************************************
  2.  * Modul  : mpsx.c                                                           *
  3.  * Zweck  : Einlesen eines files im MPSX-Standardeingabeformat               *
  4.  * Format : load <file> [-cGOAL] [-bRHS] [-rRANGES] [-uBOUNDS] [-m] [-fFILE] *
  5.  * Autor  : Stefan Förster                                                   *
  6.  *                                                                           *
  7.  * Datum      | Version | Bemerkung                                          *
  8.  * -----------|---------|--------------------------------------------------- *
  9.  * 05.03.1989 | 0.0     |                                                    *
  10.  * 07.03.1989 | 0.1     | PrintError()                                       *
  11.  * 08.03.1989 | 0.2     | Pass1()                                            *
  12.  * 09.03.1989 |         | Pass1() fertig                                     *
  13.  * 10.03.1989 | 0.3     | Zusätzliche Fehlermeldungen                        *
  14.  *            |         | SearchEl() liefert jetzt den Typ ITEMPTR           *
  15.  *            |         | ChooseSymbols(), Select()                          *
  16.  * 11.03.1989 | 0.4     | Pass2()                                            *
  17.  *            |         | Felder GLOBAL definiert                            *
  18.  * 13.03.1989 | 0.5     | Pass2() und CorrectBounds() fertig                 *
  19.  *            |         | BUG in ParseLine(): &stop[1] statt &stop[2]        *
  20.  *            |         | BUG in TakeMem(): AvailMem(NULL) statt AvailMem()  *
  21.  *            |         | BUG in ParseLine(): list[GOALS_LIST] durchsuchen   *
  22.  *            |         | BUG in MPSX(): ChooseSymbols() statt ChooseSymbols *
  23.  * 14.03.1989 | 1.0     | BUG in Pass2(): Wenn symbflag & BIT_RHS, ist       *
  24.  *            |         |                 list[RHS_LIST] leer (DeleteList()) *
  25.  *            |         | BUG in Pass2(): Fehler bei 2 Zielfkt. behoben      *
  26.  *            |         | BUG in Pass2(): RANGES: if(++i>num_lines) ...      *
  27.  *            |         | BUG in Pass2(): RANGES: num_rows+i statt m+i       *
  28.  *            |         | BUG in Pass2(): Schl.var.: Zeile iptr->nr statt i  *
  29.  *            |         | BUG in CorrectBounds(): upper[i] -= lower[i];      *
  30.  *            |         | 1. Testlauf erfolgreich                            *
  31.  * 17.03.1989 | 1.1     | zusätzlich min cTx möglich                         *
  32.  * 18.03.1989 | 1.2     | Optional Ausgabe an ein File möglich (-f)          *
  33.  *****************************************************************************/
  34.  
  35.  
  36. IMPORT STRPTR ctime(), fgets();
  37. IMPORT VOID   *AllocMem(), fclose(), SetM(), CopyMemQuick();
  38. IMPORT FILE   *fopen();
  39. IMPORT INT    fseek();
  40. IMPORT LONG   ftell(), time();
  41.  
  42. GLOBAL DOUBLE  INFINITE;
  43. GLOBAL BOOL    minimize;
  44.  
  45. GLOBAL DOUBLE  c0start, c0;
  46. GLOBAL SHORT   m, n, *B, *Nq;
  47. GLOBAL DOUBLE  *A, *AB1, *b, *b2q, *c, *c2, *upper, *lower;
  48. GLOBAL DOUBLE  *x, *cq, *pi, *dq;
  49. GLOBAL SHORT   *Nminus;
  50. GLOBAL DOUBLE  *help;
  51.  
  52. GLOBAL STRPTR  errors[];
  53.  
  54.  
  55. USHORT      symbflag;
  56. GLOBAL TEXT symbols[NUM_SYMBOLS][MAX_STRLEN+1];
  57. TEXT        filename[MAX_FILELEN+1];
  58. GLOBAL FILE *file[2];
  59. struct stat file_stat;
  60.  
  61. GLOBAL ITEMPTR list[NUM_LISTS];
  62. LONG        position[NUM_SYMBOLS];
  63.  
  64. SHORT       num_var, num_slack, num_rows, num_lines, num_goals, num_rhs;
  65. SHORT       num_ranges, num_bounds;
  66.  
  67. LONG        mm, nn;
  68.  
  69. TEXT        line_nr[9];         /* Zählvariable, max 99999999 (8 Zeichen) */
  70. TEXT        line[BUFFER];       /* eingelesene Zeile */
  71. TEXT        buf[4][BUFFER2+1];  /* Zwischenspeicher */
  72.  
  73.  
  74.  
  75.  
  76. /*****************************************************************************
  77.  * BOOL MPSX() -> _TRUE/_FALSE                                               *
  78.  * Hauptprogramm von MPSX.c                                                  *
  79.  *                                                                           *
  80.  * Input:  args   : Zeiger auf Argument-String (hinter load)                 *
  81.  *                                                                           *
  82.  * Output: _FALSE : Fehler beim Einlesen                                     *
  83.  *         _TRUE  : c0start: Korrekturwert für den Zielfunktionswert         *
  84.  *                  m,n: m und n                                             *
  85.  *                  Zeiger auf A,AB1,etc.                                    *
  86.  *****************************************************************************/
  87.  
  88. BOOL    MPSX(args)
  89.  
  90. STRPTR  args;
  91.  
  92. {
  93.   SHORT i;
  94.   BOOL  GetArgs(), Pass1(), Pass2(), ChooseSymbols(), CorrectBounds();
  95.   VOID  GetRidOfLists(), GiveMemBack();
  96.  
  97.   num_var = num_goals = num_rhs = num_ranges = num_bounds = 0;
  98.   num_slack = num_rows = num_lines = 0;
  99.  
  100.   GetRidOfLists();
  101.  
  102.   for(i=0; i<NUM_SYMBOLS; ++i) position[i] = -1L;
  103.  
  104.   if(!GetArgs(args)) return(_FALSE);
  105.  
  106.   if(!Pass1() || !ChooseSymbols() || !Pass2() || !CorrectBounds()) {
  107.     GetRidOfLists();
  108.     GiveMemBack();
  109.     return(_FALSE);
  110.   }
  111.  
  112.   return(_TRUE);
  113. }
  114.  
  115.  
  116.  
  117. /*****************************************************************************
  118.  * BOOL GetArgs() -> _TRUE/_FALSE                                            *
  119.  * wertet den Argument-String hinter load aus und setzt symbflag und         *
  120.  * symbols[][] entsprechend                                                  *
  121.  * _TRUE  : O.K. (file wurde geöffnet)                                       *
  122.  * _FALSE : Fehler aufgetreten                                               *
  123.  *****************************************************************************/
  124.  
  125. BOOL    GetArgs(str)
  126.  
  127. STRPTR  str;
  128.  
  129. {
  130.   SHORT   start, stop, length;
  131.   LONG    t;
  132.   TEXT    ch;
  133.   VOID    PrintError(), Cap();
  134.   BOOL    SearchExpr();
  135.   SHORT   GetExpr();
  136.   STRPTR  ptr;
  137.  
  138.   symbflag = 0;
  139.  
  140.   if(!SearchExpr(str,&start,&stop)) {
  141.     PrintError(ERR_INVALID_ARGS,NULL);
  142.     return(_FALSE);
  143.   }
  144.   else {   /* file-Name gefunden */
  145.     length = GetExpr(filename,str,start,stop);
  146.     if(length > MAX_FILELEN) {
  147.       PrintError(ERR_FILE_TOO_LONG,filename);
  148.       return(_FALSE);
  149.     }
  150.     else { /* und hat korrekte Länge */
  151.       if(!(file[0] = fopen(filename,"r"))) {
  152.         PrintError(errno,filename);
  153.         PrintError(ERR_NOT_READ,filename);
  154.         return(_FALSE);
  155.       }
  156.     }
  157.   }
  158.  
  159.   /* Jetzt die Argumente */
  160.  
  161.   ptr = str+stop+1;
  162.  
  163.   while(SearchExpr(ptr,&start,&stop)) {
  164.  
  165.     Cap(ptr,start,stop);
  166.  
  167.     if((length = stop-start-1)==0 && strncmp(ptr+start,"-M",2)==0)
  168.       minimize = _TRUE;
  169.  
  170.     else if(length > 0 && strncmp(ptr+start,"-F",2) == 0) {
  171.       length = GetExpr(buf[0],ptr,start+2,stop);        
  172.       if(length > MAX_FILELEN) {
  173.         PrintError(ERR_FILE_TOO_LONG,buf[0]);
  174.         return(_FALSE);
  175.       }
  176.       if(!(file[1] = fopen(buf[0],"w"))) {
  177.         PrintError(errno,buf[0]);
  178.         PrintError(ERR_NOT_WRITE,buf[0]);
  179.         return(_FALSE);
  180.       }
  181.       fputs("ASimplex Version 1.2\n",file[1]);
  182.       fputs("THE Amiga Simplex Program\n",file[1]);
  183.       fputs("(c) 18.03.1989 Stefan Förster\n\n",file[1]);
  184.       t = time(NULL);
  185.       fprintf(file[1],"Hardcopy on %s\n",ctime(&t));
  186.     }
  187.  
  188.     else {
  189.  
  190.       if(length <= 0) goto invalid; /* (stop-start+1)-2 */
  191.  
  192.       if(length > MAX_STRLEN) {
  193.         *(ptr+stop+1) = '\0';
  194.         PrintError(ERR_NAME_TOO_LONG,ptr+start+2);
  195.         return(_FALSE);
  196.       }
  197.  
  198.       if(strncmp(ptr+start,"-C",2) == 0) {
  199.         if(symbflag & BIT_GOAL) goto invalid; /* zwei Zielfkt. angegeben */
  200.         else {
  201.           symbflag |= BIT_GOAL;
  202.           strncpy(symbols[GOAL],ptr+start+2,length);
  203.           symbols[GOAL][length] = '\0';
  204.         }
  205.       }
  206.       else if(strncmp(ptr+start,"-B",2) == 0) {
  207.         if(symbflag & BIT_RHS) goto invalid;
  208.         else {
  209.           symbflag |= BIT_RHS;
  210.           strncpy(symbols[RHS],ptr+start+2,length);
  211.           symbols[RHS][length] = '\0';
  212.         }
  213.       }
  214.       else if(strncmp(ptr+start,"-R",2) == 0) {
  215.         if(symbflag & BIT_RANGES) goto invalid;
  216.         else {
  217.           symbflag |= BIT_RANGES;
  218.           strncpy(symbols[RANGES],ptr+start+2,length);
  219.           symbols[RANGES][length] = '\0';
  220.         }
  221.       }
  222.       else if(strncmp(ptr+start,"-U",2) == 0) {
  223.         if(symbflag & BIT_BOUNDS) goto invalid;
  224.         else {
  225.           symbflag |= BIT_BOUNDS;
  226.           strncpy(symbols[BOUNDS],ptr+start+2,length);
  227.           symbols[BOUNDS][length] = '\0';
  228.         }
  229.       }
  230.       else goto invalid;
  231.     }
  232.  
  233.     ptr += stop+1;
  234.  
  235.   } /* while() */
  236.  
  237.  
  238.   if(stat(filename,&file_stat) == -1) {
  239.     PrintError(errno,filename);
  240.     return(_FALSE);
  241.   }
  242.   else {
  243.     printf("== loading %s %ld bytes\n",filename,file_stat.st_size);
  244.     printf("   %s",ctime(&file_stat.st_mtime));
  245.   }
  246.  
  247.   return(_TRUE);
  248.  
  249. invalid: /* Sprungmarke (na ja) für "invalid arguments" */
  250.   PrintError(ERR_INVALID_ARGS,NULL);
  251.   return(_FALSE);
  252. }
  253.  
  254.  
  255.  
  256. /*****************************************************************************
  257.  * BOOL Pass1() -> _TRUE/_FALSE                                              *
  258.  * Pass1() durchläuft <file> zum ersten Mal. Es werden Listen der Variablen, *
  259.  * der rechten Seiten (falls noch nicht festgelegt) usw. angelegt. Außerdem  *
  260.  * erfolgt eine Syntaxüberprüfung.                                           *
  261.  * _TRUE  : OK                                                               *
  262.  * _FALSE : Fehler aufgetreten                                               *
  263.  *****************************************************************************/
  264.  
  265. BOOL Pass1()
  266.  
  267. {
  268.   LONG    count = 0, pos;
  269.   SHORT   start[5], stop[5], length;
  270.   USHORT  found = 0, actual = 0;
  271.   TEXT    ch;
  272.   STRPTR  ptr[5];
  273.   ITEMPTR iptr;
  274.   BOOL    SearchExpr(), ParseLine();
  275.   VOID    PrintError(), UpdateLine();
  276.   SHORT   GetExpr();
  277.   ITEMPTR NewListEl(), SearchEl();
  278.  
  279.   printf("P1 0");
  280.   sprintf(line_nr,"%ld",count);
  281.  
  282.   ptr[0] = line;
  283.  
  284.   /* 1. Sektion muß "NAME" sein */
  285.  
  286.   do {
  287.     if(!fgets(ptr[0],BUFFER-1,file[0])) {
  288.       if(feof(file[0])) goto finish;
  289.       if(ferror(file[0])) {
  290.         puts("");
  291.         PrintError(errno,NULL);
  292.         return(_FALSE);
  293.       }
  294.     }
  295.     UpdateLine(&count);
  296.     pos = ftell(file[0]);
  297.     Cap(ptr[0],0,BUFFER);
  298.   } while(!SearchExpr(ptr[0],&start[0],&stop[0]));
  299.   length = GetExpr(buf[0],ptr[0],start[0],stop[0]);
  300.  
  301.   if(start[0] != 0) {
  302.     puts("");
  303.     PrintError(ERR_SECTIONS,buf[0]);
  304.     PrintError(ERR_NO_NAME,buf[0]);
  305.     return(_FALSE);
  306.   }
  307.  
  308.   if(length != 4 || strncmp(buf[0],"NAME",4) != 0) {
  309.     puts("");
  310.     PrintError(ERR_NO_NAME,buf[0]);
  311.     return(_FALSE);
  312.   }
  313.  
  314.   if(!SearchExpr((ptr[1]=ptr[0]+stop[0]+1),&start[1],&stop[1])) {
  315.     puts("");
  316.     PrintError(ERR_NO_NAME,NULL);
  317.     return(_FALSE);
  318.   }
  319.   length = GetExpr(buf[1],ptr[1],start[1],stop[1]);
  320.  
  321.   if(length > MAX_STRLEN) {
  322.     puts("");
  323.     PrintError(ERR_NAME_TOO_LONG,buf[1]);
  324.     return(_FALSE);
  325.   }
  326.  
  327.   symbflag |= BIT_NAME;
  328.   found |= BIT_NAME;
  329.   strcpy(symbols[NAME],buf[1]);
  330.   position[NAME] = pos;
  331.  
  332.  
  333.   /* Jetzt folgen die anderen Sektionen */
  334.  
  335.   FOREVER {
  336.  
  337.     if(feof(file[0])) goto finish;
  338.  
  339.     if(!fgets(ptr[0],BUFFER-1,file[0])) {
  340.       if(ferror(file[0])) {
  341.         puts("");
  342.         PrintError(errno,NULL);
  343.         return(_FALSE);
  344.       }
  345.     }
  346.     UpdateLine(&count);
  347.     pos = ftell(file[0]);
  348.     Cap(ptr[0],0,BUFFER);
  349.  
  350.     if(!SearchExpr(ptr[0],&start[0],&stop[0])) continue; /* FOREVER */
  351.     length = GetExpr(buf[0],ptr[0],start[0],stop[0]);
  352.     if(length > MAX_STRLEN) {
  353.       puts("");
  354.       PrintError(ERR_NAME_TOO_LONG,buf[0]);
  355.       return(_FALSE);
  356.     }
  357.  
  358.     if(start[0] == 0) {  /* Start einer neuen Sektion */
  359.  
  360.       if(length==6 && strncmp(buf[0],"ENDATA",6) == 0) {
  361.         found |= BIT_ENDATA;
  362.         goto finish;
  363.       }
  364.       else if(length==4 && strncmp(buf[0],"ROWS",4) == 0) {
  365.         if(found & BIT_ROWS) {
  366.           puts("");
  367.           PrintError(ERR_2SECTIONS,buf[0]);
  368.           return(_FALSE);
  369.         }
  370.         else {
  371.           found |= BIT_ROWS;
  372.           actual = BIT_ROWS;
  373.           position[ROWS] = pos;
  374.           continue;
  375.         }
  376.       }
  377.       else if(length==7 && strncmp(buf[0],"COLUMNS",7) == 0) {
  378.         if(found & BIT_COLUMNS) {
  379.           puts("");
  380.           PrintError(ERR_2SECTIONS,buf[0]);
  381.           return(_FALSE);
  382.         }
  383.         else {
  384.           found |= BIT_COLUMNS;
  385.           actual = BIT_COLUMNS;
  386.           position[COLUMNS] = pos;
  387.           continue;
  388.         }
  389.       }
  390.       else if(length==3 && strncmp(buf[0],"RHS",3) == 0) {
  391.         if(found & BIT_RHS) {
  392.           puts("");
  393.           PrintError(ERR_2SECTIONS,buf[0]);
  394.           return(_FALSE);
  395.         }
  396.         else {
  397.           found |= BIT_RHS;
  398.           actual = BIT_RHS;
  399.           position[RHS] = pos;
  400.           continue;
  401.         }
  402.       }
  403.       else if(length==6 && strncmp(buf[0],"RANGES",6) == 0) {
  404.         if(found & BIT_RANGES) {
  405.           puts("");
  406.           PrintError(ERR_2SECTIONS,buf[0]);
  407.           return(_FALSE);
  408.         }
  409.         else {
  410.           found |= BIT_RANGES;
  411.           actual = BIT_RANGES;
  412.           position[RANGES] = pos;
  413.           continue;
  414.         }
  415.       }
  416.       else if(length==6 && strncmp(buf[0],"BOUNDS",6) == 0) {
  417.         if(found & BIT_BOUNDS) {
  418.           puts("");
  419.           PrintError(ERR_2SECTIONS,buf[0]);
  420.           return(_FALSE);
  421.         }
  422.         else {
  423.           found |= BIT_BOUNDS;
  424.           actual = BIT_BOUNDS;
  425.           position[BOUNDS] = pos;
  426.           continue;
  427.         }
  428.       }
  429.       else {
  430.         puts("");
  431.         PrintError(ERR_UNKNOWN_SEC,buf[0]);
  432.         return(_FALSE);
  433.       }
  434.  
  435.     }  /* if(start[0]==0) */
  436.  
  437.     else {  /* if(start[0]!=0) */
  438.  
  439.       if(actual == 0) {
  440.         puts("");
  441.         PrintError(ERR_SECTIONS,buf[0]);
  442.         return(_FALSE);
  443.       }
  444.  
  445.       switch(actual) {
  446.  
  447.         case BIT_ROWS:
  448.           if(length!=1 || (ch = buf[0][0])!='N' && ch!='E' && ch!='L' && 
  449.              ch!='G') {
  450.             puts("");
  451.             PrintError(ERR_INV_ROWS_TYPE,buf[0]);
  452.             return(_FALSE);
  453.           }
  454.           ptr[1] = ptr[0]+start[0]+1;
  455.           if(!SearchExpr(ptr[1],&start[1],&stop[1])) {
  456.             puts("");
  457.             PrintError(ERR_MISSING,NULL);
  458.             return(_FALSE);
  459.           }
  460.           length = GetExpr(buf[0]+1,ptr[1],start[1],stop[1]);
  461.           if(length > MAX_STRLEN) {
  462.             puts("");
  463.             PrintError(ERR_NAME_TOO_LONG,buf[0]+1);
  464.             return(_FALSE);
  465.           }
  466.           if(ch == 'N') {  /* Zielfunktion */
  467.             if(SearchEl(buf[0]+1,list[GOALS_LIST],_FALSE,NULL)) {
  468.               puts("");
  469.               PrintError(ERR_DOUBLE,buf[0]+1);
  470.               return(_FALSE);
  471.             }
  472.             if(!(iptr = NewListEl(list[GOALS_LIST],buf[0]+1))) return(_FALSE);
  473.             else {
  474.               if(list[GOALS_LIST]) iptr->nr = list[GOALS_LIST]->nr+1;
  475.               else                 iptr->nr = 1;
  476.               list[GOALS_LIST] = iptr;
  477.               ++num_goals;
  478.             }
  479.           }
  480.           else {   /* Typ L, G oder E */
  481.             if(SearchEl(buf[0]+1,list[ROWS_LIST],_TRUE,NULL)) {
  482.               puts("");
  483.               PrintError(ERR_DOUBLE,buf[0]+1);
  484.               return(_FALSE);
  485.             }
  486.             if(!(iptr = NewListEl(list[ROWS_LIST],buf[0]))) return(_FALSE);
  487.             else {
  488.               if(list[ROWS_LIST]) iptr->nr = list[ROWS_LIST]->nr+1;
  489.               else                iptr->nr = 1;
  490.               list[ROWS_LIST] = iptr;
  491.               ++num_rows;
  492.               if(ch == 'L' || ch == 'G') ++num_slack;
  493.             }
  494.           }
  495.           break;
  496.  
  497.         case BIT_COLUMNS:
  498.           if(!ParseLine(VAR_LIST,buf[0],stop[0])) return(_FALSE);
  499.           break;
  500.  
  501.         case BIT_RHS:
  502.           if(!ParseLine(RHS_LIST,buf[0],stop[0])) return(_FALSE);
  503.           break;
  504.  
  505.         case BIT_RANGES:
  506.           if(!ParseLine(RANGES_LIST,buf[0],stop[0])) return(_FALSE);
  507.           break;
  508.  
  509.         case BIT_BOUNDS:
  510.           if(length!=2 || (strncmp(buf[0],"UP",2)!=0 &&
  511.              strncmp(buf[0],"LO",2)!=0)) {
  512.             puts("");
  513.             PrintError(ERR_INV_BOUNDS_TYPE,buf[0]);
  514.             return(_FALSE);
  515.           }
  516.           /* Jetzt müssen drei Ausdrücke folgen */
  517.           if(!SearchExpr((ptr[1]=ptr[0]+stop[0]+1),&start[1],&stop[1]) ||
  518.              !SearchExpr((ptr[2]=ptr[1]+stop[1]+1),&start[2],&stop[2]) ||
  519.              !SearchExpr((ptr[3]=ptr[2]+stop[2]+1),&start[3],&stop[3])   ) {
  520.             puts("");
  521.             PrintError(ERR_MISSING,NULL);
  522.             return(_FALSE);
  523.           }
  524.           length = GetExpr(buf[1],ptr[1],start[1],stop[1]);
  525.           if(length > MAX_STRLEN) {
  526.             puts("");
  527.             PrintError(ERR_NAME_TOO_LONG,buf[1]);
  528.             return(_FALSE);
  529.           }
  530.           if(!SearchEl(buf[1],list[BOUNDS_LIST],_FALSE,NULL)) {
  531.             if(!(iptr = NewListEl(list[BOUNDS_LIST],buf[1]))) return(_FALSE);
  532.             else {
  533.               if(list[BOUNDS_LIST]) iptr->nr = list[BOUNDS_LIST]->nr+1;
  534.               else                  iptr->nr = 1;
  535.               list[BOUNDS_LIST] = iptr;
  536.               ++num_bounds;
  537.             }
  538.           }
  539.           length = GetExpr(buf[2],ptr[2],start[2],stop[2]);
  540.           if(length > MAX_STRLEN) {
  541.             puts("");
  542.             PrintError(ERR_NAME_TOO_LONG,buf[2]);
  543.             return(_FALSE);
  544.           }
  545.           if(!SearchEl(buf[2],list[VAR_LIST],_FALSE,NULL)) {
  546.             puts("");
  547.             PrintError(ERR_UNKNOWN_ID,buf[2]);
  548.             return(_FALSE);
  549.           }
  550.           break;
  551.  
  552.       } /* switch(actual) */
  553.     } /* else if(start[0]!=0) */
  554.   } /* FOREVER() */
  555.  
  556.  
  557. finish:  /* Sprungmarke, falls feof(file[0]) oder ENDATA erreicht */
  558.   if(!(found & BIT_ROWS) || num_rows == 0) {
  559.     puts("");
  560.     PrintError(ERR_NO_ROWS,NULL);
  561.     return(_FALSE);
  562.   }
  563.   if(!(found & BIT_COLUMNS) || num_var == 0) {
  564.     puts("");
  565.     PrintError(ERR_NO_COLUMNS,NULL);
  566.     return(_FALSE);
  567.   }
  568.   if(!(found & BIT_RHS)) {
  569.     puts("");
  570.     PrintError(ERR_NO_RHS,NULL);
  571.     return(_FALSE);
  572.   }
  573.   if(!(found & BIT_ENDATA)) {
  574.     puts("");
  575.     PrintError(ERR_NO_ENDATA,NULL);
  576.     return(_FALSE);
  577.   }
  578.   if(position[NAME] >= position[ROWS] ||
  579.      position[ROWS] >= position[COLUMNS] ||
  580.      position[COLUMNS] >= position[RHS] ||
  581.      position[RANGES] != -1 && position[BOUNDS] != -1 &&
  582.      position[RANGES] >= position[BOUNDS]                ) {
  583.     puts("");
  584.     PrintError(ERR_ORDER,NULL);
  585.     return(_FALSE);
  586.   }
  587.  
  588.   puts("");
  589.   return(_TRUE);  /* alle Fehlerfälle überstanden */
  590. }
  591.  
  592.  
  593.  
  594. /*****************************************************************************
  595.  * VOID UpdateLine()                                                         *
  596.  * Aktualisiert den Zeilenzähler von Pass1()                                 *
  597.  *****************************************************************************/
  598.  
  599. VOID UpdateLine(c)
  600.  
  601. LONG *c;
  602.  
  603. {
  604.   SHORT i, len = strlen(line_nr);
  605.  
  606.   for(i=0; i<len; ++i) printf("%c",8);
  607.   sprintf(line_nr,"%ld",++(*c));
  608.   printf("%s",line_nr);
  609. }
  610.  
  611.  
  612.  
  613. /*****************************************************************************
  614.  * BOOL ParseLine(list_type,bufptr,end0) -> _TRUE/_FALSE                     *
  615.  * Überprüft eine Zeile (aus der Sektion COLUMNS, RHS oder RANGES) auf       *
  616.  * korrekte Syntax. bufptr ist Zeiger auf den Puffer, der den ersten Aus-    *
  617.  * druck der Zeile enthält. Falls dieser noch nicht in der jeweiligen Liste  *
  618.  * enthalten ist, wird er angefügt. list_type kann die Werte VAR_LIST,       *
  619.  * RHS_LIST oder RANGES_LIST annehmen. end0 ist stop[0] von Pass1()          *
  620.  * _TRUE  : O.K.                                                             *
  621.  * _FALSE : Fehler aufgetreten                                               *
  622.  *****************************************************************************/
  623.  
  624. BOOL    ParseLine(list_type,bufptr,end0)
  625.  
  626. SHORT   list_type;
  627. STRPTR  bufptr;
  628. SHORT   end0;
  629.  
  630. {
  631.   SHORT   start[5], stop[5], length;
  632.   TEXT    ch;
  633.   STRPTR  ptr[5];
  634.   ITEMPTR iptr, dptr;
  635.   ITEMPTR NewListEl(), SearchEl();
  636.  
  637.  
  638.   ptr[0] = line; /* wie auch in Pass1() */
  639.  
  640.   if(!(dptr = SearchEl(bufptr,list[list_type],_FALSE,NULL))) { /* neue Var. */
  641.     if(!(iptr = NewListEl(list[list_type],bufptr))) return(_FALSE);
  642.     else {
  643.       if(list[list_type]) iptr->nr = list[list_type]->nr+1;
  644.       else                iptr->nr = 1;
  645.       if(list_type == RANGES_LIST) iptr->anz = 0;
  646.       list[list_type] = iptr;
  647.       switch(list_type) {
  648.         case VAR_LIST:    ++num_var;
  649.                           break;
  650.         case RHS_LIST:    ++num_rhs;
  651.                           break;
  652.         case RANGES_LIST: ++num_ranges;
  653.                           break;
  654.       }
  655.       dptr = iptr;
  656.     }
  657.   }
  658.   /* dptr zeigt jetzt auf den 1.Eintrag der Zeile */
  659.   ptr[1] = ptr[0]+end0+1; /* mind. 2 Ausdrücke in dieser Zeile */
  660.   if(!SearchExpr(ptr[1],&start[1],&stop[1]) ||
  661.      !SearchExpr((ptr[2] = ptr[1]+stop[1]+1),&start[2],&stop[2])) {
  662.     puts("");
  663.     PrintError(ERR_MISSING,NULL);
  664.     return(_FALSE);
  665.   }
  666.   length = GetExpr(buf[1],ptr[1],start[1],stop[1]);
  667.   if(length > MAX_STRLEN) {
  668.     puts("");
  669.     PrintError(ERR_NAME_TOO_LONG,buf[1]);
  670.     return(_FALSE);
  671.   }
  672.   ch = '\0';
  673.   if(!SearchEl(buf[1],list[ROWS_LIST],_TRUE,&ch) &&
  674.      !SearchEl(buf[1],list[GOALS_LIST],_FALSE,NULL) ) {
  675.     puts("");
  676.     PrintError(ERR_UNKNOWN_ID,buf[1]);
  677.     return(_FALSE);
  678.   }
  679.   if(list_type == RANGES_LIST && ch == 'E') {
  680.     puts("");
  681.     PrintError(ERR_INV_RANGES,buf[1]);
  682.     return(_FALSE);
  683.   }
  684.   if(list_type == RANGES_LIST) ++dptr->anz;
  685.   ptr[3] = ptr[2]+stop[2]+1; /* noch mehr (genau 2) ? */
  686.   if(SearchExpr(ptr[3],&start[3],&stop[3])) {
  687.     ptr[4] = ptr[3]+stop[3]+1;
  688.     if(!SearchExpr(ptr[4],&start[4],&stop[4])) {
  689.       puts("");
  690.       PrintError(ERR_MISSING,NULL);
  691.       return(_FALSE);
  692.     }
  693.     else {
  694.       length = GetExpr(buf[3],ptr[3],start[3],stop[3]);
  695.       if(length > MAX_STRLEN) {
  696.         puts("");
  697.         PrintError(ERR_NAME_TOO_LONG,buf[3]);
  698.         return(_FALSE);
  699.       }
  700.       ch = '\0';
  701.       if(!SearchEl(buf[3],list[ROWS_LIST],_TRUE,&ch) &&
  702.          !SearchEl(buf[3],list[GOALS_LIST],_FALSE,NULL) ) {
  703.         puts("");
  704.         PrintError(ERR_UNKNOWN_ID,buf[3]);
  705.         return(_FALSE);
  706.       }
  707.       if(list_type == RANGES_LIST && ch == 'E') {
  708.         puts("");
  709.         PrintError(ERR_INV_RANGES,buf[1]);
  710.         return(_FALSE);
  711.       }
  712.       if(list_type == RANGES_LIST) ++dptr->anz;
  713.     }
  714.   }
  715.  
  716.   return(_TRUE);
  717. }
  718.  
  719.  
  720.  
  721. /*****************************************************************************
  722.  * BOOL ChooseSymbols() -> _TRUE/_FALSE                                      *
  723.  * Legt endgültig die Bezeichner der Zielfunktion, der rechten Seite, des    *
  724.  * Bereichs und der Grenzen fest. Außerdem wird num_lines ermittelt.         *
  725.  * _TRUE  : O.K.                                                             *
  726.  * _FALSE : Fehler aufgetreten                                               *
  727.  *****************************************************************************/
  728.  
  729. BOOL ChooseSymbols()
  730.  
  731. {
  732.   ITEMPTR dptr;
  733.   ITEMPTR Select(), SearchEl();
  734.   VOID    DeleteList();
  735.  
  736.  
  737.   if(!(symbflag & BIT_GOAL)) {
  738.     if(num_goals == 0) {
  739.       PrintError(ERR_NO_GOAL,NULL);
  740.       return(_FALSE);
  741.     }
  742.     else if(num_goals == 1) {
  743.       strcpy(symbols[GOAL],list[GOALS_LIST]->string);
  744.       symbflag |= BIT_GOAL;
  745.     }
  746.     else {
  747.       if(!(dptr = Select(list[GOALS_LIST],"Possible goals"))) return(_FALSE);
  748.       else {
  749.         strcpy(symbols[GOAL],dptr->string);
  750.         symbflag |= BIT_GOAL;
  751.       }
  752.     }
  753.   }
  754.   else if(!SearchEl(symbols[GOAL],list[GOALS_LIST],_FALSE,NULL)) {
  755.     PrintError(ERR_NO_GOAL,NULL);
  756.     return(_FALSE);
  757.   }
  758.   DeleteList(&list[GOALS_LIST]);
  759.  
  760.   /* Ist Zielfunktion schon als normale Zeile deklariert ? */
  761.   if(SearchEl(symbols[GOAL],list[ROWS_LIST],_TRUE,NULL)) {
  762.     PrintError(ERR_DOUBLE,symbols[GOAL]);
  763.     return(_FALSE);
  764.   }
  765.  
  766.   if(!(symbflag & BIT_RHS) && num_rhs>0) {
  767.     if(num_rhs == 1) {
  768.       strcpy(symbols[RHS],list[RHS_LIST]->string);
  769.       symbflag |= BIT_RHS;
  770.     }
  771.     else {
  772.       if(!(dptr = Select(list[RHS_LIST],"Possible right hand sides")))
  773.         return(_FALSE);
  774.       else {
  775.         strcpy(symbols[RHS],dptr->string);
  776.         symbflag |= BIT_RHS;
  777.       }
  778.     }
  779.   }
  780.   DeleteList(&list[RHS_LIST]);
  781.  
  782.   if(symbflag & BIT_RANGES) {
  783.     if(dptr = SearchEl(symbols[RANGES],list[RANGES_LIST],_FALSE,NULL))
  784.          num_lines = dptr->anz;
  785.     else num_lines = 0;
  786.   }
  787.   else {
  788.     if(num_ranges == 0) num_lines = 0;
  789.     else if(num_ranges == 1) {
  790.       strcpy(symbols[RANGES],list[RANGES_LIST]->string);
  791.       symbflag |= BIT_RANGES;
  792.       num_lines = list[RANGES_LIST]->anz;
  793.     }
  794.     else {
  795.       if(!(dptr = Select(list[RANGES_LIST],"Possible ranges"))) return(_FALSE);
  796.       else {
  797.         strcpy(symbols[RANGES],dptr->string);
  798.         symbflag |= BIT_RANGES;
  799.         num_lines = dptr->anz;
  800.       }
  801.     }
  802.   }
  803.   DeleteList(&list[RANGES_LIST]);
  804.  
  805.   if(!(symbflag & BIT_BOUNDS) && num_bounds>0) {
  806.     if(num_bounds == 1) {
  807.       strcpy(symbols[BOUNDS],list[BOUNDS_LIST]->string);
  808.       symbflag |= BIT_BOUNDS;
  809.     }
  810.     else {
  811.       if(!(dptr = Select(list[BOUNDS_LIST],"Possible bounds")))
  812.         return(_FALSE);
  813.       else {
  814.         strcpy(symbols[BOUNDS],dptr->string);
  815.         symbflag |= BIT_BOUNDS;
  816.       }
  817.     }
  818.   }
  819.   DeleteList(&list[BOUNDS_LIST]);
  820.  
  821.   return(_TRUE);
  822.  
  823. }
  824.  
  825.  
  826.  
  827. /*****************************************************************************
  828.  * ITEMPTR Select(lptr,str)                                                  *
  829.  * Auswahl eines Eintrags der Liste lptr durch den Benutzer.                 *
  830.  * Ergebnis ist der Zeiger auf den gewählten Eintrag, NULL, falls ein Fehler *
  831.  * aufgetreten ist.  lptr != NULL wird angenommen. Zu Beginn wird der String *
  832.  * str ausgegeben.                                                           *
  833.  *****************************************************************************/
  834.  
  835. ITEMPTR Select(lptr,str)
  836.  
  837. ITEMPTR lptr;
  838. STRPTR  str;
  839.  
  840. {
  841.   ITEMPTR ptr = lptr;
  842.   SHORT   count = 0, atoi(), choice, i;
  843.   INT     GetInput(), error;
  844.  
  845.   printf("?? %s:\n",str);
  846.  
  847.   while(ptr) {
  848.     printf("   %-8s  %3d\n",ptr->string,++count);
  849.     ptr = ptr->next;
  850.   }
  851.  
  852.   do {
  853.     printf("?? Your choice : ");
  854.     if(error = GetInput(line)) {
  855.       PrintError(error,NULL);
  856.       return(NULL);
  857.     }
  858.   } while((choice = atoi(line)) <= 0 || choice > count);
  859.  
  860.   ptr = lptr;
  861.   for(i=1; i<choice; ++i) ptr = ptr->next;
  862.  
  863.   return(ptr);
  864. }
  865.  
  866.  
  867.  
  868. /*****************************************************************************
  869.  * BOOL Pass2() -> _TRUE/_FALSE                                              *
  870.  * Pass2() stellt den Speicherplatz bereit und liest die Daten in die er-    *
  871.  * zeugten Felder ein.                                                       *
  872.  * _TRUE  : O.K.                                                             *
  873.  * _FALSE : Fehler aufgetreten                                               *
  874.  *****************************************************************************/
  875.  
  876. BOOL Pass2()
  877.  
  878. {
  879.   TEXT    ch;
  880.   SHORT   i, j, count, start[5], stop[5], length;
  881.   STRPTR  ptr[5];
  882.   ITEMPTR iptr;
  883.   DOUBLE  *ptr1, *ptr2;
  884.   ITEMPTR SearchEl();
  885.   SHORT   GetExpr();
  886.   BOOL    TakeMem(), SearchExpr();
  887.   VOID    Cap();
  888.   DOUBLE  atof();
  889.  
  890.  
  891.   ptr[0] = line;
  892.  
  893.   m = num_rows+num_lines;
  894.   n = num_var+num_slack+num_lines;
  895.  
  896.   mm = (LONG)m;
  897.   nn = (LONG)n;
  898.  
  899.   if(!TakeMem()) return(_FALSE);
  900.  
  901.   printf("P2 NAME    %s\n",symbols[NAME]);
  902.   if(file[1]) fprintf(file[1],"P2 NAME    %s\n",symbols[NAME]);
  903.  
  904.   /* A auf Schlupfvariablen vorbereiten */
  905.  
  906.   iptr = list[ROWS_LIST];
  907.   for(count=0; iptr; iptr=iptr->next) {
  908.     if((ch = *iptr->string) == 'L') SetM(A,n,iptr->nr,num_var+(++count),1.0);
  909.     else if(ch == 'G')              SetM(A,n,iptr->nr,num_var+(++count),-1.0);
  910.   }
  911.  
  912.   /* COLUMNS-Sektion einlesen */
  913.  
  914.   printf("P2 COLUMNS\n");
  915.   if(file[1]) fprintf(file[1],"P2 COLUMNS\n");
  916.   if(fseek(file[0],position[COLUMNS],0) == -1) {
  917.     PrintError(errno,NULL);
  918.     return(_FALSE);
  919.   }
  920.  
  921.   do {
  922.     if(!fgets(ptr[0],BUFFER-1,file[0])) {
  923.       if(ferror(file[0])) {
  924.         PrintError(errno,NULL);
  925.         return(_FALSE);
  926.       }
  927.     }
  928.     Cap(ptr[0],0,BUFFER);
  929.  
  930.     if(SearchExpr(ptr[0],&start[0],&stop[0])) {
  931.  
  932.       if(start[0] == 0) break; /* Abbruch von do{}while, Beginn neuer Sektion */
  933.       length = GetExpr(buf[0],ptr[0],start[0],stop[0]);
  934.       if(!(iptr = SearchEl(buf[0],list[VAR_LIST],_FALSE,NULL))) {
  935.         PrintError(ERR_FATAL,NULL);
  936.         return(_FALSE);
  937.       }
  938.       j = iptr->nr;  /* Spalte */
  939.  
  940.       if(SearchExpr((ptr[1] = ptr[0]+stop[0]+1),&start[1],&stop[1]) &&
  941.          SearchExpr((ptr[2] = ptr[1]+stop[1]+1),&start[2],&stop[2])    ) {
  942.         length = GetExpr(buf[1],ptr[1],start[1],stop[1]);
  943.         length = GetExpr(buf[2],ptr[2],start[2],stop[2]);
  944.         if(strcmp(symbols[GOAL],buf[1]) == 0)
  945.           c[j-1] = minimize ? -atof(buf[2]) : atof(buf[2]);
  946.         else {
  947.           if(iptr = SearchEl(buf[1],list[ROWS_LIST],_TRUE,NULL))
  948.             SetM(A,n,iptr->nr,j,atof(buf[2]));
  949.         }
  950.  
  951.         if(SearchExpr((ptr[3] = ptr[2]+stop[2]+1),&start[3],&stop[3]) &&
  952.           SearchExpr((ptr[4] = ptr[3]+stop[3]+1),&start[4],&stop[4])    ) {
  953.           length = GetExpr(buf[1],ptr[3],start[3],stop[3]);
  954.           length = GetExpr(buf[2],ptr[4],start[4],stop[4]);
  955.           if(strcmp(symbols[GOAL],buf[1]) == 0)
  956.             c[j-1] = minimize ? -atof(buf[2]) : atof(buf[2]);
  957.           else {
  958.             if(iptr = SearchEl(buf[1],list[ROWS_LIST],_TRUE,NULL))
  959.               SetM(A,n,iptr->nr,j,atof(buf[2]));
  960.           }
  961.         }
  962.       }
  963.     }
  964.  
  965.   } while(!feof(file[0]));
  966.  
  967.  
  968.   /* RHS-Sektion einlesen */
  969.  
  970.   if(symbflag & BIT_RHS && position[RHS]!=-1) {
  971.  
  972.     printf("P2 RHS     %s\n",symbols[RHS]);
  973.     if(file[1]) fprintf(file[1],"P2 RHS     %s\n",symbols[RHS]);
  974.  
  975.     if(fseek(file[0],position[RHS],0) == -1) {
  976.       PrintError(errno,NULL);
  977.       return(_FALSE);
  978.     }
  979.  
  980.     do {
  981.       if(!fgets(ptr[0],BUFFER-1,file[0])) {
  982.         if(ferror(file[0])) {
  983.           PrintError(errno,NULL);
  984.           return(_FALSE);
  985.         }
  986.       }
  987.       Cap(ptr[0],0,BUFFER);
  988.  
  989.       if(SearchExpr(ptr[0],&start[0],&stop[0])) {
  990.  
  991.         if(start[0] == 0) break; /* Abbruch von do{}while, neue Sektion */
  992.         length = GetExpr(buf[0],ptr[0],start[0],stop[0]);
  993.         if(strcmp(symbols[RHS],buf[0]) == 0) {
  994.           if(SearchExpr((ptr[1] = ptr[0]+stop[0]+1),&start[1],&stop[1]) &&
  995.              SearchExpr((ptr[2] = ptr[1]+stop[1]+1),&start[2],&stop[2])    ) {
  996.             length = GetExpr(buf[1],ptr[1],start[1],stop[1]);
  997.             if(!(iptr = SearchEl(buf[1],list[ROWS_LIST],_TRUE,NULL))) {
  998.               PrintError(ERR_FATAL,NULL);
  999.               return(_FALSE);
  1000.             }
  1001.             i = iptr->nr;
  1002.             length = GetExpr(buf[2],ptr[2],start[2],stop[2]);
  1003.             b[i-1] = atof(buf[2]);
  1004.  
  1005.             if(SearchExpr((ptr[3] = ptr[2]+stop[2]+1),&start[3],&stop[3]) &&
  1006.                SearchExpr((ptr[4] = ptr[3]+stop[3]+1),&start[4],&stop[4])    ) {
  1007.               length = GetExpr(buf[1],ptr[3],start[3],stop[3]);
  1008.               if(!(iptr = SearchEl(buf[1],list[ROWS_LIST],_TRUE,NULL))) {
  1009.                 PrintError(ERR_FATAL,NULL);
  1010.                 return(_FALSE);
  1011.               }
  1012.               i = iptr->nr;
  1013.               length = GetExpr(buf[2],ptr[4],start[4],stop[4]);
  1014.               b[i-1] = atof(buf[2]);
  1015.             }
  1016.           }
  1017.         }
  1018.       }
  1019.     } while(!feof(file[0]));
  1020.   }
  1021.  
  1022.  
  1023.   /* RANGES-Sektion einlesen */
  1024.  
  1025.   if(symbflag & BIT_RANGES && num_lines!=0 && position[RANGES]!=-1) {
  1026.  
  1027.     printf("P2 RANGES  %s\n",symbols[RANGES]);
  1028.     if(file[1]) fprintf(file[1],"P2 RANGES  %s\n",symbols[RANGES]);
  1029.  
  1030.     if(fseek(file[0],position[RANGES],0) == -1) {
  1031.       PrintError(errno,NULL);
  1032.       return(_FALSE);
  1033.     }
  1034.  
  1035.     i = 0;  /* Zähler für zusätzliche Zeilen */
  1036.     do {
  1037.       if(!fgets(ptr[0],BUFFER-1,file[0])) {
  1038.         if(ferror(file[0])) {
  1039.           PrintError(errno,NULL);
  1040.           return(_FALSE);
  1041.         }
  1042.       }
  1043.       Cap(ptr[0],0,BUFFER);
  1044.  
  1045.       if(SearchExpr(ptr[0],&start[0],&stop[0])) {
  1046.  
  1047.         if(start[0] == 0) break; /* Abbruch von do{}while, neue Sektion */
  1048.         length = GetExpr(buf[0],ptr[0],start[0],stop[0]);
  1049.  
  1050.         if(strcmp(buf[0],symbols[RANGES]) == 0) {
  1051.  
  1052.           if(SearchExpr((ptr[1] = ptr[0]+stop[0]+1),&start[1],&stop[1]) &&
  1053.              SearchExpr((ptr[2] = ptr[1]+stop[1]+1),&start[2],&stop[2])   ) {
  1054.             length = GetExpr(buf[1],ptr[1],start[1],stop[1]);
  1055.             if(!(iptr = SearchEl(buf[1],list[ROWS_LIST],_TRUE,NULL))) {
  1056.               PrintError(ERR_FATAL,NULL);
  1057.               return(_FALSE);
  1058.             }
  1059.             if(++i > num_lines) {
  1060.               PrintError(ERR_FATAL,NULL);
  1061.               return(_FALSE);
  1062.             }
  1063.             ptr1 = A+(LONG)(iptr->nr-1)*nn;
  1064.             ptr2 = A+(LONG)(num_rows+i-1)*nn;
  1065.             CopyMemQuick(ptr1,ptr2,(LONG)((LONG)num_var*S_DOUBLE));
  1066.             length = GetExpr(buf[2],ptr[2],start[2],stop[2]);
  1067.             if(*iptr->string == 'L') {
  1068.               SetM(A,n,num_rows+i,num_var+num_slack+i,-1.0);
  1069.               b[num_rows+i-1] = b[iptr->nr-1]-atof(buf[2]);
  1070.             }
  1071.             else {
  1072.               SetM(A,n,num_rows+i,num_var+num_slack+i,1.0);
  1073.               b[num_rows+i-1] = b[iptr->nr-1]+atof(buf[2]);
  1074.             }
  1075.  
  1076.             if(SearchExpr((ptr[3] = ptr[2]+stop[2]+1),&start[3],&stop[3]) &&
  1077.               SearchExpr((ptr[4] = ptr[3]+stop[3]+1),&start[4],&stop[4])   ) {
  1078.               length = GetExpr(buf[1],ptr[3],start[3],stop[3]);
  1079.               if(!(iptr = SearchEl(buf[1],list[ROWS_LIST],_TRUE,NULL))) {
  1080.                 PrintError(ERR_FATAL,NULL);
  1081.                 return(_FALSE);
  1082.               }
  1083.               if(++i > num_lines) {
  1084.                 PrintError(ERR_FATAL,NULL);
  1085.                 return(_FALSE);
  1086.               }
  1087.               ptr1 = A+(LONG)(iptr->nr-1)*nn;
  1088.               ptr2 = A+(LONG)(num_rows+i-1)*nn;
  1089.               CopyMemQuick(ptr1,ptr2,(LONG)((LONG)num_var*S_DOUBLE));
  1090.               length = GetExpr(buf[2],ptr[4],start[4],stop[4]);
  1091.               if(*iptr->string == 'L') {
  1092.                 SetM(A,n,num_rows+i,num_var+num_slack+i,-1.0);
  1093.                 b[num_rows+i-1] = b[iptr->nr-1]-atof(buf[2]);
  1094.               }
  1095.               else {
  1096.                 SetM(A,n,num_rows+i,num_var+num_slack+i,1.0);
  1097.                 b[num_rows+i-1] = b[iptr->nr-1]+atof(buf[2]);
  1098.               }
  1099.             }
  1100.           }
  1101.         }
  1102.       }
  1103.     } while(!feof(file[0]));
  1104.   }
  1105.  
  1106.  
  1107.   /* BOUNDS-Sektion einlesen */
  1108.  
  1109.   if(symbflag & BIT_BOUNDS && position[BOUNDS]!=-1) {
  1110.  
  1111.     printf("P2 BOUNDS  %s\n",symbols[BOUNDS]);
  1112.     if(file[1]) fprintf(file[1],"P2 BOUNDS  %s\n",symbols[BOUNDS]);
  1113.  
  1114.     if(fseek(file[0],position[BOUNDS],0) == -1) {
  1115.       PrintError(errno,NULL);
  1116.       return(_FALSE);
  1117.     }
  1118.  
  1119.     do {
  1120.       if(!fgets(ptr[0],BUFFER-1,file[0])) {
  1121.         if(ferror(file[0])) {
  1122.           PrintError(errno,NULL);
  1123.           return(_FALSE);
  1124.         }
  1125.       }
  1126.       Cap(ptr[0],0,BUFFER);
  1127.  
  1128.       if(SearchExpr(ptr[0],&start[0],&stop[0])) {
  1129.  
  1130.         if(start[0] == 0) break; /* Abbruch von do{}while, neue Sektion */
  1131.         length = GetExpr(buf[0],ptr[0],start[0],stop[0]);
  1132.  
  1133.         if(SearchExpr((ptr[1] = ptr[0]+stop[0]+1),&start[1],&stop[1]) &&
  1134.            SearchExpr((ptr[2] = ptr[1]+stop[1]+1),&start[2],&stop[2]) &&
  1135.            SearchExpr((ptr[3] = ptr[2]+stop[2]+1),&start[3],&stop[3])   ) {
  1136.           length = GetExpr(buf[1],ptr[1],start[1],stop[1]);
  1137.           if(strcmp(buf[1],symbols[BOUNDS]) == 0) {
  1138.             length = GetExpr(buf[2],ptr[2],start[2],stop[2]);
  1139.             if(!(iptr = SearchEl(buf[2],list[VAR_LIST],_FALSE,NULL))) {
  1140.               PrintError(ERR_FATAL,NULL);
  1141.               return(_FALSE);
  1142.             }
  1143.             length = GetExpr(buf[3],ptr[3],start[3],stop[3]);
  1144.             if(buf[0][0] == 'U') upper[iptr->nr-1] = atof(buf[3]);
  1145.             else                 lower[iptr->nr-1] = atof(buf[3]);
  1146.           }
  1147.         }
  1148.       }
  1149.     } while(!feof(file[0]));
  1150.   }
  1151.  
  1152.   return(_TRUE);
  1153. }
  1154.  
  1155.  
  1156.  
  1157. /*****************************************************************************
  1158.  * BOOL CorrectBounds() -> _TRUE/_FALSE                                      *
  1159.  * Anpassung des Gleichungssystems an lower == 0, Berechnung von c0start     *
  1160.  * und rechte Seite b >= 0 machen.                                           *
  1161.  * _TRUE  : O.K.                                                             *
  1162.  * _FALSE : ERR_UP_LO                                                        *
  1163.  *****************************************************************************/
  1164.  
  1165. BOOL CorrectBounds()
  1166.  
  1167. {
  1168.   REGISTER DOUBLE *ptr1, dummy;
  1169.   REGISTER SHORT  j, i;
  1170.   BOOL            found = _FALSE;
  1171.   VOID            PrintError();
  1172.  
  1173.   for(i=0; i<num_var; ++i) {
  1174.     if(upper[i] != INFINITE && lower[i] > upper[i]) {
  1175.       PrintError(ERR_UP_LO,NULL);
  1176.       return(_FALSE);
  1177.     }
  1178.     if(lower[i] != 0.0) found = _TRUE;
  1179.     if(upper[i] != INFINITE)  upper[i] -= lower[i];
  1180.   }
  1181.  
  1182.   if(found) {
  1183.     for(i=0; i<m; ++i) {
  1184.       ptr1 = A+(LONG)i*nn;
  1185.       for(dummy=0.0,j=0; j<num_var; ++j) dummy += (*ptr1++)*lower[j];
  1186.       b[i] -= dummy;
  1187.     }
  1188.     for(c0start=0.0,j=0; j<num_var; ++j) c0start += c[j]*lower[j];
  1189.   }
  1190.   else c0start = 0.0;
  1191.  
  1192.   for(i=0; i<m; ++i) {
  1193.     if(b[i] < 0.0) {
  1194.       ptr1 = A+(LONG)i*nn;
  1195.       for(j=0; j<n; ++j) *ptr1++ *= -1.0;
  1196.       b[i] *= -1.0;
  1197.     }
  1198.   }
  1199.  
  1200.  
  1201.   return(_TRUE);
  1202. }
  1203.  
  1204.  
  1205.  
  1206. /*****************************************************************************
  1207.  * BOOL SearchExpr(str,start,stop) -> _TRUE/_FALSE                           *
  1208.  * Sucht den ersten Ausdruck im String str und bestimmt die Position des     *
  1209.  * ersten (start) und letzten (stop) Zeichens in str.                        *
  1210.  * _TRUE  : O.K.                                                             *
  1211.  * _FALSE : kein Ausdruck gefunden                                           *
  1212.  *****************************************************************************/
  1213.  
  1214. BOOL    SearchExpr(str,start,stop)
  1215.  
  1216. STRPTR  str;
  1217. SHORT   *start, *stop;
  1218.  
  1219. {
  1220.   TEXT            ch;
  1221.   REGISTER SHORT  pos1 = 0, pos2;
  1222.  
  1223.   /* Trennzeichen überspringen */
  1224.   while((ch = str[pos1]) != '\0' && isspace(ch)) ++pos1;
  1225.  
  1226.   if(ch == '\0') return(_FALSE); /* Stringende erreicht, kein Ausdruck vorh. */
  1227.  
  1228.   pos2 = pos1+1;
  1229.   while((ch = str[pos2]) != '\0' && !isspace(ch)) ++pos2;
  1230.  
  1231.   *start = pos1;
  1232.   *stop = pos2-1;
  1233.   return(_TRUE);
  1234. }
  1235.  
  1236.  
  1237.  
  1238. /*****************************************************************************
  1239.  * SHORT GetExpr(dest,ptr,start,stop)                                        *
  1240.  * Kopiert den Ausdruck, der bei ptr+start beginnt und bei ptr+stop endet,   *
  1241.  * nach dest. Danach werden alle Kleinbuchstaben zu Großbuchstaben. Das Er-  *
  1242.  * gebnis ist die Länge des Ausdrucks                                        *
  1243.  *****************************************************************************/
  1244.  
  1245. SHORT   GetExpr(dest,ptr,start,stop)
  1246.  
  1247. STRPTR  dest, ptr;
  1248. SHORT   start, stop;
  1249.  
  1250. {
  1251.   SHORT length, reallength;
  1252.  
  1253.   length = stop-start+1;
  1254.   reallength = length>BUFFER2-1 ? BUFFER2-1 : length; /* verhindert Überlauf */
  1255.   strncpy(dest,ptr+start,reallength);
  1256.   dest[reallength] = '\0';
  1257.   return(length);
  1258. }
  1259.  
  1260.  
  1261.  
  1262. /*****************************************************************************
  1263.  * VOID Cap(str,start,stop)                                                  *
  1264.  * String str in Großbuchstaben umwandeln (von start bis einschl. stop)      *
  1265.  * Cap() bricht ab, falls stop oder das Stringende erreicht sind             *
  1266.  *****************************************************************************/
  1267.  
  1268. VOID    Cap(str,start,stop)
  1269.  
  1270. STRPTR  str;
  1271. SHORT   start, stop;
  1272.  
  1273. {
  1274.   REGISTER SHORT pos;
  1275.   TEXT           ch;
  1276.  
  1277.   for(pos = start; pos<=stop && (ch=str[pos])!='\0'; ++pos) {
  1278.     if(isalpha(ch) && islower(ch)) str[pos] = toupper(ch);
  1279.   }
  1280. }
  1281.  
  1282.  
  1283.  
  1284. /*****************************************************************************
  1285.  * ITEMPTR NewListEl(list,str)                                               *
  1286.  * Fügt an die Liste list ein neues Element an (an den Anfang) und übergibt  *
  1287.  * den neuen Listenanker. Falls dieser NULL ist, ERR_MEM. Außerdem wird der  *
  1288.  * String str in das neue Listenelement kopiert                              *
  1289.  *****************************************************************************/
  1290.  
  1291. ITEMPTR NewListEl(list,str)
  1292.  
  1293. ITEMPTR list;
  1294. STRPTR  str;
  1295.  
  1296. {
  1297.   VOID    PrintError();
  1298.   ITEMPTR ptr;
  1299.  
  1300.   if(ptr = AllocMem(SIZE_ITEM,MEMF_CLEAR)) {
  1301.     ptr->next = list;
  1302.     strcpy(ptr->string,str);
  1303.   }
  1304.   else PrintError(ERR_MEM,NULL);
  1305.  
  1306.   return(ptr);
  1307. }
  1308.  
  1309.  
  1310.  
  1311. /*****************************************************************************
  1312.  * ITEMPTR SearchEl(str,list,spezial,chstr)                                  *
  1313.  * Sucht den String str in der Liste list. Ist spezial==_TRUE, so wird erst  *
  1314.  * ab dem zweiten Zeichen verglichen (für spezielles Format von ROWS_LIST).  *
  1315.  * Wird bufstr != NULL angegeben, so wird das erste Zeichen des gefundenen   *
  1316.  * Strings dort hineingeschrieben (Format für ROWS_LIST).                    *
  1317.  * Ergebnis ist entweder der Zeiger auf den gefundenen Eintrag, oder NULL,   *
  1318.  * falls str nicht in der Liste enthalten ist                                *
  1319.  *****************************************************************************/
  1320.  
  1321. ITEMPTR SearchEl(str,list,spezial,chstr)
  1322.  
  1323. STRPTR  str;
  1324. ITEMPTR list;
  1325. BOOL    spezial;
  1326. STRPTR  chstr;    /* Zeiger auf Character */
  1327.  
  1328. {
  1329.   ITEMPTR ptr = list;
  1330.   STRPTR  sptr;
  1331.  
  1332.   while(ptr) {
  1333.     sptr = spezial ? ptr->string+1 : ptr->string;
  1334.     if(strcmp(str,sptr)==0) {
  1335.       if(chstr) *chstr = *ptr->string;
  1336.       return(ptr);
  1337.     }
  1338.     ptr = ptr->next;
  1339.   }
  1340.  
  1341.   return(NULL);
  1342. }
  1343.  
  1344.  
  1345.  
  1346. /*****************************************************************************
  1347.  * VOID DeleteList(list)                                                     *
  1348.  * Löscht die Liste list. Vorsicht: list ist Zeiger auf Zeiger !!            *
  1349.  *****************************************************************************/
  1350.  
  1351. VOID    DeleteList(list)
  1352.  
  1353. ITEMPTR *list;
  1354.  
  1355. {
  1356.   if(*list) {
  1357.     DeleteList(&(*list)->next);
  1358.     FreeMem(*list,SIZE_ITEM);
  1359.     *list = NULL;
  1360.   }
  1361. }
  1362.  
  1363.  
  1364.  
  1365. /*****************************************************************************
  1366.  * VOID GetRidOfLists()                                                      *
  1367.  * Löscht alle Bezeichnerlisten                                              *
  1368.  *****************************************************************************/
  1369.  
  1370. VOID GetRidOfLists()
  1371.  
  1372. {
  1373.   SHORT i;
  1374.   VOID  DeleteList();
  1375.  
  1376.   for(i=0; i<NUM_LISTS; ++i) DeleteList(&list[i]);
  1377. }
  1378.  
  1379.  
  1380.  
  1381. /*****************************************************************************
  1382.  * VOID PrintError(nr,str)                                                   *
  1383.  * Gibt die Fehlermeldung zur Fehlernummer nr aus, optional davor einen      *
  1384.  * String str.
  1385.  * 0 <= nr <= sys_nerr : vorgegebene Systemfehlermeldungen                   *
  1386.  * nr > sys_nerr       : eigene Fehlermeldungen                              *
  1387.  *****************************************************************************/
  1388.  
  1389. VOID    PrintError(nr,str)
  1390. INT     nr;
  1391. STRPTR  str;
  1392.  
  1393. {
  1394.   printf(":: Error %2d : ",nr);
  1395.   if(str) printf("(%s) ",str);
  1396.   if(nr<=sys_nerr) printf("%s\n",sys_errlist[nr]);
  1397.   else             printf("%s\n",errors[nr-sys_nerr-1]);
  1398.  
  1399.   if(file[1]) {
  1400.     fprintf(file[1],":: Error %2d : ",nr);
  1401.     if(str) fprintf(file[1],"(%s) ",str);
  1402.     if(nr<=sys_nerr) fprintf(file[1],"%s\n",sys_errlist[nr]);
  1403.     else             fprintf(file[1],"%s\n",errors[nr-sys_nerr-1]);
  1404.   }
  1405. }
  1406.  
  1407.  
  1408.  
  1409. /*****************************************************************************
  1410.  * INT GetInput(str)                                                         *
  1411.  * Liest eine Zeile von der Console (=stdin) in den String "str" ein         *
  1412.  * Ergebnis: Fehlernummer bzw. 0, falls kein Fehler auftrat                  *
  1413.  *****************************************************************************/
  1414.  
  1415. INT     GetInput(str)
  1416. STRPTR  str;
  1417. {
  1418.   STRPTR  gets();
  1419.  
  1420.   if(!gets(str)) {
  1421.     if(feof(stdin)) return(ERR_EOF); /* nur, wenn stdin != Console ist */
  1422.     else if(ferror(stdin)) return(errno);
  1423.   }
  1424.  
  1425.   return(0);
  1426. }
  1427.  
  1428.  
  1429.  
  1430. /*****************************************************************************
  1431.  * BOOL TakeMem() -> _TRUE/_FALSE                                            *
  1432.  * TakeMem() alloziert den Speicher für die Felder.                          *
  1433.  * _TRUE  : O.K.                                                             *
  1434.  * _FALSE : ERR_MEM                                                          *
  1435.  *****************************************************************************/
  1436.  
  1437. BOOL TakeMem()
  1438.  
  1439. {
  1440.   LONG  mem_needed, mem_avail, i;
  1441.   LONG  AvailMem();
  1442.   VOID  GiveMemBack(), PrintError();
  1443.  
  1444.   mem_needed = S_SHORT*(mm+2L*nn)+S_DOUBLE*(mm*(mm+nn+8L)+6L*nn);
  1445.  
  1446.   if(mem_needed > (mem_avail = AvailMem(NULL))) {
  1447.     sprintf(line,"%ld needed,%ld available",mem_needed,mem_avail);
  1448.     PrintError(ERR_MEM,line);
  1449.     return(_FALSE);
  1450.   }
  1451.  
  1452.   A       = AllocMem(mm*nn*S_DOUBLE,MEMF_CLEAR);
  1453.   AB1     = AllocMem(mm*mm*S_DOUBLE,MEMF_CLEAR);
  1454.   b       = AllocMem(mm*S_DOUBLE,MEMF_CLEAR);
  1455.   b2q     = AllocMem(mm*S_DOUBLE,MEMF_CLEAR);
  1456.   c       = AllocMem(nn*S_DOUBLE,MEMF_CLEAR);
  1457.   c2      = AllocMem((nn+mm)*S_DOUBLE,MEMF_CLEAR);
  1458.   upper   = AllocMem((nn+mm)*S_DOUBLE,NULL);
  1459.   lower   = AllocMem(nn*S_DOUBLE,MEMF_CLEAR);
  1460.   x       = AllocMem((nn+mm)*S_DOUBLE,MEMF_CLEAR);
  1461.   cq      = AllocMem(nn*S_DOUBLE,MEMF_CLEAR);
  1462.   pi      = AllocMem(mm*S_DOUBLE,MEMF_CLEAR);
  1463.   dq      = AllocMem(mm*S_DOUBLE,MEMF_CLEAR);
  1464.   help    = AllocMem(mm*S_DOUBLE,MEMF_CLEAR);
  1465.  
  1466.   B       = AllocMem(mm*S_SHORT,MEMF_CLEAR);
  1467.   Nq      = AllocMem(nn*S_SHORT,MEMF_CLEAR);
  1468.   Nminus  = AllocMem(nn*S_SHORT,MEMF_CLEAR);
  1469.  
  1470.   if(!(A && AB1 && b && b2q && c && c2 && upper && lower && x && cq && pi &&
  1471.        dq && help && B && Nq && Nminus)) {
  1472.     GiveMemBack();
  1473.     PrintError(ERR_MEM,NULL);
  1474.     return(_FALSE);
  1475.   }
  1476.  
  1477.   for(i=0; i<(nn+mm); ++i) upper[i] = INFINITE;
  1478.  
  1479.   return(_TRUE);
  1480. }
  1481.  
  1482.  
  1483.  
  1484. /*****************************************************************************
  1485.  * VOID GiveMemBack()                                                        *
  1486.  * Allozierten Speicher an das System zurückgeben.                           *
  1487.  *****************************************************************************/
  1488.  
  1489. VOID GiveMemBack()
  1490.  
  1491. {
  1492.   if(A)       FreeMem(A,mm*nn*S_DOUBLE);
  1493.   if(AB1)     FreeMem(AB1,mm*mm*S_DOUBLE);
  1494.   if(b)       FreeMem(b,mm*S_DOUBLE);
  1495.   if(b2q)     FreeMem(b2q,mm*S_DOUBLE);
  1496.   if(c)       FreeMem(c,nn*S_DOUBLE);
  1497.   if(c2)      FreeMem(c2,(nn+mm)*S_DOUBLE);
  1498.   if(upper)   FreeMem(upper,(nn+mm)*S_DOUBLE);
  1499.   if(lower)   FreeMem(lower,nn*S_DOUBLE);
  1500.   if(x)       FreeMem(x,(nn+mm)*S_DOUBLE);
  1501.   if(cq)      FreeMem(cq,nn*S_DOUBLE);
  1502.   if(pi)      FreeMem(pi,mm*S_DOUBLE);
  1503.   if(dq)      FreeMem(dq,mm*S_DOUBLE);
  1504.   if(help)    FreeMem(help,mm*S_DOUBLE);
  1505.  
  1506.   if(B)       FreeMem(B,mm*S_SHORT);
  1507.   if(Nq)      FreeMem(Nq,nn*S_SHORT);
  1508.   if(Nminus)  FreeMem(Nminus,nn*S_SHORT);
  1509.  
  1510.   A = AB1 = b = b2q = c = c2 = upper = lower = x = cq = pi = dq = help = NULL;
  1511.  
  1512.   B = Nq = Nminus = NULL;
  1513. }
  1514.